<!DOCTYPE html>
<html lang="en">

<head>
    <title> 创建默认元素 </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <!-- 3D 库 -->
    <script src="../库/babylon.max.js"></script>
    <style>
        html,
        body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #renderCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
    </style>
    <script>
        var $ = {};
        // 元素创建代码
        var element = function (scene) {
            // 设置形状官方资料: http://doc.babylonjs.com/how_to/set_shapes
            // API(MeshBuilder)资料: https://doc.babylonjs.com/api/classes/babylon.meshbuilder#createsphere
            // 创建形状的代码
            //-> <Shape Name> 形状名字
            //-> "name"  形状命名
            //-> options 参数
            //-> scene   场景
            // var mesh = BABYLON.MeshBuilder.Create<Shape Name>("name", options, scene);
            //------------------------------------注-----------------------------------------------------
            /*
                创建参数部分并不难,在此就不在详细翻译了.
                参数前 * 号是重点需要关注的.
                -> 网格可更新(updatable) 用于动画/变换的.
                -> 前面UV(frontUVs)/后面UV(backUVs)
                    这是给一个面对象正面背面添加不同的UI.
                    https://doc.babylonjs.com/how_to/frontandbackuv
            */
            //---------------------------------测试代码--------------------------------------------------
            //-> 创建 盒子(Box) 命名为: box 盒子高度: 5 
            /*
            // 默认参数
                尺寸 (size)   默认 1
                高度 (height) 默认 size
                宽度 (width)  默认 size
                深度 (depth)  默认 size
                颜色 (faceColors) Color4类型*6   默认 Color4(1, 1, 1, 1)*6 或 size 面颜色
                UV   (faceUV)     Vector4类型*6  默认 UVs(0, 0, 1, 1)*6 或 size UV信息
                * 网格可更新(updatable) 默认 false
                * 排序方向 (sideOrientation) 为0的时候正面隐藏只能看到形状的反面，为1时看到的是正面，为2时为双面显示
                * 前面UV(frontUVs) 	 
                * 后面UV(backUVs)
            // 排列顺序(Side Orientation)
                BABYLON.Mesh.FRONTSIDE, //前面
                BABYLON.Mesh.BACKSIDE,  //后面
                BABYLON.Mesh.DOUBLESIDE,//双面
                BABYLON.Mesh.DEFAULT    //默认值，等同于前面
            */
            var box = BABYLON.MeshBuilder.CreateBox("box", { height: 5 }, scene);
            box.position.x = 10;
            box.position.y = 10;
            //-> 创建 球体(Sphere)
            var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2, diameterX: 3 }, scene);
            sphere.position.x = 20;
            sphere.position.y = 10;
            //-> 创建 圆柱/圆锥(Cylinder)
            var cone = BABYLON.MeshBuilder.CreateCylinder("cone", { diameterTop: 0, tessellation: 4 }, scene);
            cone.position.x = 30;
            cone.position.y = 10;
            //-> 创建 平面(Plane)
            var plane = BABYLON.MeshBuilder.CreatePlane("plane", { width: 5 }, scene);
            plane.position.x = 40;
            plane.position.y = 10;
            //-> 创建 圆盘/正多边形(Disc)
            var disc = BABYLON.MeshBuilder.CreateDisc("disc", { tessellation: 3 }, scene);
            disc.position.x = 50;
            disc.position.y = 10;
            //-> 创建 圆环(Torus)
            var torus = BABYLON.MeshBuilder.CreateTorus("torus", { thickness: 0.2 }, scene);
            torus.position.x = 60;
            torus.position.y = 10;
            //-> 创建 环面纽结(Torus Knot)
            var torusknot = BABYLON.MeshBuilder.CreateTorusKnot("tk", {}, scene);
            torusknot.position.x = 70;
            torusknot.position.y = 10;
            //-> 创建 地面(Ground)
            var ground = BABYLON.MeshBuilder.CreateGround("gd", { width: 6, subdivsions: 4 }, scene);
            ground.position.x = 80;
            ground.position.y = 10;
            //-> 创建 高度地面(GroundFromHeightMap)
            var groundfrom = BABYLON.MeshBuilder.CreateGroundFromHeightMap("gdhm", 'https://i.imgur.com/LW12uEN.jpg', { width: 6, subdivisions: 4 }, scene);
            groundfrom.position.x = 90;
            groundfrom.position.y = 10;
            //-> 创建 瓷砖地面(TiledGround)
            // 瓷砖地面资料:  https://makina-corpus.com/blog/metier/2014/how-to-use-multimaterials-with-a-tiled-ground-in-babylonjs
            // 可参考当前默认代码部分的创建瓷砖地面
            var tiledGround = BABYLON.MeshBuilder.CreateTiledGround("tgd", { subdivsions: { w: 4, h: 6 } }, scene);
            tiledGround.position.x = 100;
            tiledGround.position.y = 10;
        };
        // 默认创建代码
        window.addEventListener('DOMContentLoaded', function () {
            // 获得元素
            var canvas = document.getElementById('renderCanvas');
            // 创建渲染
            var engine = new BABYLON.Engine(canvas, true);
            // 隔离创建
            var scene = (function () {
                // 创建一个基本的Scene对象，用来容纳所有其他对象
                var scene = new BABYLON.Scene(engine);
                // 创建一个相机，设置其位置为
                var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 20, -10), scene);
                // 相机聚焦在场景原点位置
                camera.setTarget(BABYLON.Vector3.Zero());
                // 使得我们可以控制相机拍摄角度，和three.js中的OrbitsControl效果类似，但简单得多
                camera.attachControl(canvas, false);
                camera.position.y = 10;
                camera.position.z = -40;
                camera.rotation.x = -0.1;
                camera.rotation.y = 0;
                //----------------------创建元素-------------------
                // 注意元素创建需要 scene 对象
                element(scene)
                //----------------------创建瓷砖地面------------------- 
                var xmin = -200;
                var zmin = -200;
                var xmax = 200;
                var zmax = 200;
                var precision = {
                    "w": 20,
                    "h": 20
                };
                var subdivisions = {
                    'h': 20,
                    'w': 20
                };
                // 地面瓷砖对象
                var tiledGround = new BABYLON.Mesh.CreateTiledGround("Tiled Ground", xmin, zmin, xmax, zmax, subdivisions, precision, scene);
                // 材料
                var whiteMaterial = new BABYLON.StandardMaterial("White", scene);
                whiteMaterial.diffuseColor = new BABYLON.Color3(1, 1, 1);
                var blackMaterial = new BABYLON.StandardMaterial("Black", scene);
                blackMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
                // 多材料
                var multimat = new BABYLON.MultiMaterial("multi", scene);
                multimat.subMaterials.push(whiteMaterial);
                multimat.subMaterials.push(blackMaterial);
                // 给地面对象设置材料
                tiledGround.material = multimat;
                // 获得面/顶点信息
                var verticesCount = tiledGround.getTotalVertices();
                var tileIndicesLength = tiledGround.getIndices().length / (subdivisions.w * subdivisions.h);
                // 设置子网格
                tiledGround.subMeshes = [];
                var base = 0;
                for (var row = 0; row < subdivisions.h; row++) {
                    for (var col = 0; col < subdivisions.w; col++) {
                        tiledGround.subMeshes.push(new BABYLON.SubMesh(row % 2 ^ col % 2, 0, verticesCount, base, tileIndicesLength, tiledGround));
                        base += tileIndicesLength;
                    }
                }
                // 返回 Scene对象一个半球形光源,朝向为天空
                var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
                return scene;
            })();
            // 循环渲染
            engine.runRenderLoop(function () {
                scene.render();
            });
            //追加事件：帆布与大小调整程序
            window.addEventListener('resize', function () {
                engine.resize();
            });
        });
    </script>
</head>

<body>
    <canvas id="renderCanvas"></canvas>
</body>

</html>